package com.micro.ai.models.config;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 网关认证过滤器
 * 
 * 从网关添加的请求头中提取用户信息，设置到 Spring Security Context 中
 * 
 * 网关会在认证成功后添加以下请求头：
 * - X-User-Id: 用户ID
 * - X-Username: 用户名
 * - X-Tenant-Id: 租户ID
 * - X-User-Roles: 用户角色（逗号分隔）
 * - X-User-Permissions: 用户权限（逗号分隔）
 * 
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@Component
public class GatewayAuthFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain
    ) throws ServletException, IOException {
        
        // 从请求头中提取用户信息
        String userId = request.getHeader("X-User-Id");
        String username = request.getHeader("X-Username");
        String tenantId = request.getHeader("X-Tenant-Id");
        String rolesHeader = request.getHeader("X-User-Roles");
        String permissionsHeader = request.getHeader("X-User-Permissions");
        
        // 调试日志：打印所有请求头
        log.info("=== GatewayAuthFilter 调试信息 ===");
        log.info("请求路径: {}", request.getRequestURI());
        log.info("X-User-Id: {}", userId);
        log.info("X-Username: {}", username);
        log.info("X-Tenant-Id: {}", tenantId);
        log.info("X-User-Roles: {}", rolesHeader);
        log.info("X-User-Permissions: {}", permissionsHeader);
        
        // 如果网关已经验证并传递了用户信息，则设置认证状态
        if (StringUtils.hasText(userId)) {
            log.debug("从网关获取用户信息 - UserId: {}, Username: {}, TenantId: {}", userId, username, tenantId);
            
            // 解析角色和权限
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            
            if (StringUtils.hasText(rolesHeader)) {
                String[] roles = rolesHeader.split(",");
                for (String role : roles) {
                    if (StringUtils.hasText(role.trim())) {
                        authorities.add(new SimpleGrantedAuthority("ROLE_" + role.trim()));
                    }
                }
            }
            
            if (StringUtils.hasText(permissionsHeader)) {
                String[] permissions = permissionsHeader.split(",");
                for (String permission : permissions) {
                    if (StringUtils.hasText(permission.trim())) {
                        authorities.add(new SimpleGrantedAuthority(permission.trim()));
                    }
                }
            }
            
            // 创建认证对象
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(
                            userId,
                            null,
                            authorities
                    );

            // 设置详细信息（可以在其他地方通过 RequestAttribute 获取）
            authentication.setDetails(new GatewayUserDetails(userId, username, tenantId));

            // 设置到 Spring Security Context
            SecurityContextHolder.getContext().setAuthentication(authentication);
            
            // 将 userId 添加到请求属性中，供后端控制器使用
            request.setAttribute("userId", userId);
            request.setAttribute("username", username);
            request.setAttribute("tenantId", tenantId);
            
            log.info("✅ 用户认证成功 - UserId: {}, Username: {}, TenantId: {}, Authorities: {}", 
                    userId, username, tenantId, authorities);
        } else {
            log.warn("❌ 网关未传递用户信息，跳过认证 - 请求将无法通过Spring Security");
        }
        
        filterChain.doFilter(request, response);
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        String path = request.getRequestURI();
        
        // 公开接口不需要网关认证
        return path.startsWith("/api/auth/login") ||
               path.startsWith("/api/auth/register") ||
               path.startsWith("/api/auth/captcha") ||
               path.startsWith("/api/auth/logout") ||
               path.startsWith("/api/auth/sms-code") ||
               path.startsWith("/api/users/register") ||
               path.startsWith("/doc.html") ||
               path.startsWith("/swagger-ui") ||
               path.startsWith("/v3/api-docs") ||
               path.startsWith("/swagger-resources") ||
               path.startsWith("/webjars") ||
               path.startsWith("/favicon.ico") ||
               path.startsWith("/actuator") ||
               path.startsWith("/error");
    }

    /**
     * 网关用户详细信息
     */
    public static class GatewayUserDetails {
        private final String userId;
        private final String username;
        private final String tenantId;

        public GatewayUserDetails(String userId, String username, String tenantId) {
            this.userId = userId;
            this.username = username;
            this.tenantId = tenantId;
        }

        public String getUserId() {
            return userId;
        }

        public String getUsername() {
            return username;
        }

        public String getTenantId() {
            return tenantId;
        }
    }
}

